package pl.peterjack.model;

import java.text.DecimalFormat;

public class Slownie {

	private static String[] jednostki = { "Zero", "Jeden", "Dwa", "Trzy",
			"Cztery", "Pięć", "Sześć", "Siedem", "Osiem", "Dziewięć",
			"Dziesięć", "Jedenaście", "Dwanaście", "Trzynaście", "Czternaście",
			"Piętnaście", "Szesnaście", "Siedemnaście", "Osiemnaście",
			"Dziewiętnaście" };

	private static String[] dziesietne = { "Dwadzieścia", "Trzydzieści",
			"Czterdzieści", "Pięćdziesiąt", "Sześćdziesiąt", "Siedemdziesiąt",
			"Osiemdziesiąt", "Dziewięćdziesiąt" };

	private static String[] setne = { "", "Sto", "Dwieście", "Trzysta",
			"Czterysta", "Pięćset", "Sześćset", "Siedemset", "Osiemset",
			"Dziewięćset" };

	private static String[][] inneJednostki = {
			{ "Tysiąc", "Tysiące", "Tysięcy" },
			{ "Milion", "Miliony", "Milionów" },
			{ "Miliard", "Miliardy", "Miliardów" } };

	private static String konwersjaMalychLiczb(int n) {
		if (n == 0) {
			return null;
		}

		StringBuilder sb = new StringBuilder();

		// Konwertuj setki.
		int temp = n / 100;
		if (temp > 0) {
			sb.append(setne[temp]);
			n -= temp * 100;
		}

		// Konwertuj dziesiątki i jedności.

		if (n > 0) {
			if (sb.length() > 0) {
				sb.append(" ");
			}

			if (n < 20) {
				// Liczby poniżej 20 przekonwertuj na podstawie
				// tablicy jedności.

				sb.append(jednostki[n]);
			} else {
				// Większe liczby przekonwertuj łącząc nazwy
				// krotności dziesiątek z nazwami jedności.
				sb.append(dziesietne[(n / 10) - 2]);
				int lastDigit = n % 10;

				if (lastDigit > 0) {
					sb.append(" ");
					sb.append(jednostki[lastDigit]);
				}
			}
		}
		return sb.toString();
	}

	private static int obliczeniaDlaDuzychLiczb(long n) {
		int ostatnia = (int) n % 10;

		if ((n >= 10 && (n <= 20 || ostatnia == 0)) || (ostatnia > 4)) {
			return 2;
		}
		return (ostatnia == 1) ? 0 : 1;
	}

	private static long naSlowa(StringBuilder valueInWords, long n, int level) {
		int malaWartosc = 0;
		long dzielnik = (long) Math.pow(1000, (long) level + 1);

		if (dzielnik <= n) {
			// Jeśli liczbę da się podzielić przez najbliższą
			// potęgę 1000, kontynuuj rekurencję.
			n = naSlowa(valueInWords, n, level + 1);
			malaWartosc = (int) (n / dzielnik);
			if (valueInWords.length() > 0) {
				valueInWords.append(" ");
			}

			if (malaWartosc > 1) {
				valueInWords.append(konwersjaMalychLiczb(malaWartosc));
				valueInWords.append(" ");
			}
			valueInWords
					.append(inneJednostki[level][obliczeniaDlaDuzychLiczb(malaWartosc)]);
		}

		return n - malaWartosc * dzielnik;
	}

	private static String naSlowa(long value) {
		if (value == 0) {
			return jednostki[0];
		}
		StringBuilder valueInWords = new StringBuilder();
		int smallValue = (int) naSlowa(valueInWords, value, 0);
		if (smallValue > 0) {
			if (valueInWords.length() > 0) {
				valueInWords.append(" ");
			}
			valueInWords.append(konwersjaMalychLiczb(smallValue));
		}
		return valueInWords.toString();
	}

	private static long liczbaZlotych(double kwota) {
		DecimalFormat dfx = new DecimalFormat("0");
		String szlote = dfx.format(kwota);
		Long dzlote = new Long(szlote);
		return (long) dzlote;
	}

	private static long liczbaGroszy(double grosze) {
		// Tworzę format zmiennych aby uzyskać liczbę w frmie tekstowej
		DecimalFormat dfx = new DecimalFormat("0.00");
		String szlote = dfx.format(grosze);
		// Odcinam grosze
		String bgzlote = (String) szlote.substring(0, szlote.length() - 3);
		Double dzlote = new Double(bgzlote);
		// Od kwoty z groszami odejmuję kwotę bez.
		Long groszy = (long) (grosze * 100 - dzlote * 100);
		return groszy;
	}

	public static String procKwotaSlownie(double kwota) {
		// glowna metoda
		if (kwota < 0) {
			kwota = kwota * -1;
		}
		String strKwotaSl = "";
		strKwotaSl = naSlowa(liczbaZlotych(kwota)) + " zł "
				+ naSlowa(liczbaGroszy(kwota)) + " gr.";
		return strKwotaSl;
	}

	public static String procKwotaSlownie(float kwota) {
		return procKwotaSlownie((double) kwota);
	}
}